package validation

import (
	"context"
	"errors"
	"gorm.io/gen"
	"gorm.io/gorm"
	"mall_frontend_api/biz/consts"
	"mall_frontend_api/biz/dal"
	"mall_frontend_api/biz/lib/biz_error"
	"mall_frontend_api/biz/model"
	"mall_frontend_api/biz/model/common"
	"mall_frontend_api/biz/model/order"
	"mall_frontend_api/biz/util"
)

func CheckCreateOrder(ctx context.Context, req *order.CreateOrderRequest, userInfo *model.UserInfo) (int64, error) {
	var total float64
	if req.Type == common.CreateOrderType_Product {
		if req.SKUID == "" {
			return 0, biz_error.NewBizError().SetLogMessage("skuID").SetBadRequestErrorMessage("The product has been taken down, please add it again")
		}
		_, err := dao.ProductDAO.GetInfoByID(ctx, req.GetProductID())
		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
			return 0, biz_error.NewBizError().SetLogMessage("dal GetProductInfoByID").SetServerErrorMessage(err.Error())
		}

		if errors.Is(err, gorm.ErrRecordNotFound) {
			return 0, biz_error.NewBizError().SetLogMessage("dal GetProductInfoByID").SetBadRequestErrorMessage("The product has been taken down, please add it again")
		}

		if req.GetProductNumber() <= 0 {
			return 0, biz_error.NewBizError().SetLogMessage("number error").SetBadRequestErrorMessage("The quantity of the product is incorrect")
		}

		productItemList, err := dao.ProductItemDAO.GetList(ctx, []gen.Condition{dal.ProductItem.ProductID.Eq(req.ProductID)}, 0, 0)
		if err != nil {
			return 0, biz_error.NewBizError().SetLogMessage("dal GetProductItemList").SetServerErrorMessage(err.Error())
		}

		var sku bool
		for _, item := range productItemList {
			if item.SkuID == req.GetSKUID() {
				sku = true
				total = item.SellPrice * float64(req.ProductNumber)
			}
		}
		if !sku {
			return 0, biz_error.NewBizError().SetLogMessage("dal GetProductItemList").SetBadRequestErrorMessage("The SKU of the product does not exist, please add it again")
		}
	} else {
		cartMap, err := dao.CartDAO.MGet(ctx, req.CartIDs)
		if err != nil {
			return 0, biz_error.NewBizError().SetLogMessage("dal MGetCart").SetServerErrorMessage(err.Error())
		}
		var productIDs []int64
		var skuIDs []string
		for _, cart := range cartMap {
			productIDs = append(productIDs, cart.ProductID)
			skuIDs = append(skuIDs, cart.SkuID)
		}
		skuIDs = util.Unique(skuIDs)
		productIDs = util.Unique(productIDs)
		productMap, err := dao.ProductDAO.MGet(ctx, productIDs)
		if err != nil {
			return 0, biz_error.NewBizError().SetLogMessage("dal ProductDAO").SetServerErrorMessage(err.Error())
		}
		if len(productMap) < len(productIDs) {
			return 0, biz_error.NewBizError().SetLogMessage("购物车商品有下架").SetBadRequestErrorMessage("The submitted product has been taken down, please place a new order")
		}
		productItemMap, err := dao.ProductItemDAO.MGetByProductIDs(ctx, productIDs)
		if err != nil {
			return 0, biz_error.NewBizError().SetLogMessage("dal ProductItemDAO").SetServerErrorMessage(err.Error())
		}
		var skuMap = make(map[string]float64)
		for _, items := range productItemMap {
			for _, item := range items {
				skuMap[item.SkuID] = item.SellPrice
			}
		}
		for _, cart := range cartMap {
			if p, ok := skuMap[cart.SkuID]; ok {
				total += float64(cart.Number) * p
			}
		}
	}

	if req.PaymentType.String() == consts.UNSET {
		return 0, biz_error.NewBizError().SetLogMessage("PaymentType").SetServerErrorMessage("PaymentType is required")
	}

	if req.PaymentType == common.PaymentType_Points {
		uInfo, err := dao.UserDAO.GetInfoByID(ctx, userInfo.ID)
		if err != nil {
			return 0, biz_error.NewBizError().SetLogMessage("dal GetUserInfoByID").SetServerErrorMessage(err.Error())
		}
		if uInfo.Points < int64(total*100) {
			return 0, biz_error.NewBizError().SetLogMessage("user point不够").SetBadRequestErrorMessage("Insufficient points, please recharge and try again")
		}
	}

	userAddress, err := dao.UserAddressDAO.GetInfoByID(ctx, req.UserAddressID)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return 0, biz_error.NewBizError().SetLogMessage("dal GetUserAddressByID").SetServerErrorMessage(err.Error())
	}

	if errors.Is(err, gorm.ErrRecordNotFound) {
		return 0, biz_error.NewBizError().SetLogMessage("dal GetUserAddressByID").SetBadRequestErrorMessage("The user address does not exist")
	}

	if userAddress.UserID != userInfo.ID {
		return 0, biz_error.NewBizError().SetLogMessage("dal GetUserAddressByID").SetBadRequestErrorMessage("The user address does not belong to the user")
	}

	return int64(total * 100), nil
}

func CheckGetOrderInfo(ctx context.Context, req *order.GetOrderInfoRequest, userInfo *model.UserInfo) error {
	orderInfo, err := dao.OrderDAO.GetInfoByID(ctx, req.ID)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return biz_error.NewBizError().SetLogMessage("dao.OrderDAO.GetInfoByID").SetServerErrorMessage(err.Error())
	}
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return biz_error.NewBizError().SetLogMessage("CheckGetOrderInfo").SetBadRequestErrorMessage("The order does not exist, please add it again")
	}

	if orderInfo.UserID != userInfo.ID {
		return biz_error.NewBizError().SetLogMessage("CheckGetOrderInfo user id 不同").SetBadRequestErrorMessage("The user order does not belong to the user")
	}

	return nil
}

func CheckCancelOrder(ctx context.Context, req *order.CancelOrderRequest, userInfo *model.UserInfo) error {
	orderInfo, err := dao.OrderDAO.GetInfoByID(ctx, req.ID)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return biz_error.NewBizError().SetLogMessage("dao.OrderDAO.GetInfoByID").SetServerErrorMessage(err.Error())
	}
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return biz_error.NewBizError().SetLogMessage("CheckCancelOrder").SetBadRequestErrorMessage("The order does not exist, please add it again")
	}

	if orderInfo.UserID != userInfo.ID {
		return biz_error.NewBizError().SetLogMessage("CheckCancelOrder user id 不同").SetBadRequestErrorMessage("The user order does not belong to the user")
	}

	if orderInfo.Status != common.OrderStatus_PendingPayment {
		return biz_error.NewBizError().SetLogMessage("错误的状态").SetBadRequestErrorMessage("This order does not support cancellation")
	}
	return nil
}

func CheckPaymentOrder(ctx context.Context, req *order.PaymentOrderRequest, userInfo *model.UserInfo) error {
	orderInfo, err := dao.OrderDAO.GetInfoByID(ctx, req.ID)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return biz_error.NewBizError().SetLogMessage("dao.OrderDAO.GetInfoByID").SetServerErrorMessage(err.Error())
	}
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return biz_error.NewBizError().SetLogMessage("CheckPaymentOrder").SetBadRequestErrorMessage("The order does not exist, please add it again")
	}

	if orderInfo.UserID != userInfo.ID {
		return biz_error.NewBizError().SetLogMessage("CheckPaymentOrder user id 不同").SetBadRequestErrorMessage("The user order does not belong to the user")
	}

	if orderInfo.Status != common.OrderStatus_PendingPayment {
		return biz_error.NewBizError().SetLogMessage("错误的状态").SetBadRequestErrorMessage("The order status is not unpaid, unable to make payment")
	}
	return nil
}

func CheckConfirmReceiptOrder(ctx context.Context, req *order.ConfirmReceiptOrderRequest, userInfo *model.UserInfo) error {
	orderInfo, err := dao.OrderDAO.GetInfoByID(ctx, req.ID)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return biz_error.NewBizError().SetLogMessage("dao.OrderDAO.GetInfoByID").SetServerErrorMessage(err.Error())
	}
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return biz_error.NewBizError().SetLogMessage("CheckPaymentOrder").SetBadRequestErrorMessage("The order does not exist, please add it again")
	}

	if orderInfo.UserID != userInfo.ID {
		return biz_error.NewBizError().SetLogMessage("CheckPaymentOrder user id 不同 order:%d  login:%d", orderInfo.UserID, userInfo.ID).SetBadRequestErrorMessage("The user order does not belong to the user")
	}

	if orderInfo.Status != common.OrderStatus_DeliveryCompleted {
		return biz_error.NewBizError().SetLogMessage("错误的状态").SetBadRequestErrorMessage("The order status is not unpaid, unable to make payment")
	}
	return nil
}
